home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / pcrsep89.arc / CA.ASM < prev    next >
Assembly Source File  |  1990-03-21  |  22KB  |  757 lines

  1. comment |
  2.    Library routines for cellular automoton programs.
  3.    These routines can be used with programs written
  4.    in assembly language, Quick Basic, or C.
  5.    Save as   CA.ASM
  6.    Compile:  MASM CA;
  7.        or:  TASM CA  (ignore Location Counter Overflow warning)
  8.        |
  9.  
  10. ;  Include the next 2 lines if you use Turbo Assembler:
  11. ;        MASM51
  12. ;        QUIRKS
  13.  
  14.         EXTRN    CaCell:FAR
  15.         
  16.         .Model    Medium,Pascal    ;Required for Quick Basic
  17.         .Data
  18.  
  19. Modetype    struc            ;Default values for each mode
  20.   mcols        dw        ?    ;Columns in the univers
  21.   mrows        dw        ?    ;Rows in the universe
  22.   mvidseg    dw        ?    ;Segment of video buffer
  23.   mclear    dw        ?    ;Pointer to vid clear routine
  24.   mdisp        dw        ?    ;Pointer to display routine
  25.   mbufclr    dw        ?    ;Pointer to buffer clear routine
  26.   mvoffset    dw        ?    ;Allignment value for text buffers
  27.   mdotrep    dw        ?    ;Dot duplications per cell  |graphics
  28.   mrowrep    dw        ?    ;Row duplications per cell  |only
  29.   mchar        db        ?    ;Default display character
  30.   mcolor    db        ?    ;Default display color
  31.   mborder    db        ?    ;Default border value
  32.   mvmode    db        ?    ;Video mode to use
  33. Modetype    ends
  34.  
  35. ;        Mode 1 alters characters for monochrome adapter
  36. mode1    Modetype <80,25,        \
  37.           0b000h,        \
  38.           offset txt_disp_clear,\
  39.           offset txt_disp_buf,    \
  40.           offset txt_buf_clear,    \
  41.           0,0,0,        \
  42.           ' ', 07h, ' ', 7 >
  43.  
  44. ;        Mode 2 alters display attributes for monochrome adapter
  45. mode2    Modetype <80,25,        \
  46.           0b000h,        \
  47.           offset txt_disp_clear,\
  48.           offset txt_disp_buf,    \
  49.           offset clr_buf_clear,    \
  50.           1,0,0,        \
  51.           ' ', 07h, ' ', 7 >
  52.  
  53. ;        Mode 3 alters display characters in CGA text mode
  54. mode3    Modetype <80,25,        \
  55.           0b800h,        \
  56.           offset txt_disp_clear,\
  57.           offset txt_disp_buf,    \
  58.           offset txt_buf_clear,    \
  59.           0,0,0,        \
  60.           ' ', 07h, ' ', 3 >
  61.  
  62. ;        Mode 4 alters display colors in CGA text mode
  63. mode4    Modetype <80,25,        \
  64.           0b800h,        \
  65.           offset txt_disp_clear,\
  66.           offset txt_disp_buf,    \
  67.           offset clr_buf_clear,    \
  68.           1,0,0,        \
  69.           ' ', 07h, ' ', 3 >
  70.  
  71. ;        Mode 5 uses CGA 4-color graphics (320x200 Medium resolution)
  72. mode5    modetype <320,199,        \
  73.           0b800h,         \
  74.           offset CGA_disp_clear,\
  75.           offset CGA_disp_buf,    \
  76.           offset clr_buf_clear,    \
  77.           0,1,1,        \
  78.           0, 0, 0, 4 >
  79.  
  80. ;        Mode 6 uses EGA/VGA 16-color graphics
  81. mode6    modetype <320,175,        \
  82.           0a000h,        \
  83.           offset EGA_disp_clear,\
  84.           offset EGA_disp_buf,    \
  85.           offset clr_buf_clear,    \
  86.           0,2,2,        \
  87.           0, 0, 0, 10h >
  88.  
  89. maxmode        equ    6
  90. modetbl        dw    mode1, mode2, mode3, mode4, mode5, mode6
  91.  
  92. rows        dw    ?
  93. cols        dw    ?
  94. vidseg        dw    ?
  95. clear_val    equ    this word
  96.   clear_char    db    ?
  97.   clear_color    db    ?
  98. border_on    dw    1            ;0 = off, 1 = on
  99. row_repeat    dw    ?
  100. dot_repeat    dw    ?
  101. voffset        dw    ?            ;0 = chars, 1 = colors
  102. border_val    db    ?
  103.  
  104. EVEN
  105. bufcols        dw    ?            ;Columns in buffer
  106. bufsize        dw    ?            ;Total buffer size
  107. bufaddr        equ    this dword
  108.   bufstart    dw    0000h
  109.   bufseg    dw    seg ca_buf
  110.  
  111. cell_array    dw    ?            ;Offset of cell info array 
  112. disp_clear_addr    dw    ?
  113. disp_buf_addr    dw    ?
  114. buf_clear_addr    dw    ?
  115. original_mode    dw    ?            ;Original video mode
  116.  
  117. ;ca_buf        segment                ;64K universe buffer
  118. ;        dw    8000h dup (?)
  119. ;ca_buf        ends
  120.  
  121.         .code
  122. ;************
  123. ;  CaInit -- initializes the CA universe and video adapter.
  124. ;    Call:    CaInit (Mode_number, Array_address_offset)
  125. ;    Returns: 1 = succes, 0 = failure
  126. ;************
  127.     Public    CaInit
  128. CaInit        proc    far mode_num,array_ptr
  129.         test    original_mode,-1    ;Mode already changed?
  130.         jnz    @F            ;Yes -- go
  131.         mov    ah,0fh            ;Else read video mode
  132.         int    10h            ;Call BIOS
  133.         sub    ah,ah            ;Ready to restore mode
  134.         mov    [original_mode],ax    ;Save original mode
  135.     @@:    mov    ax,0            ;Ready to report failure
  136.         mov    bx,mode_num        ;Get requested mode
  137.         or    bx,bx            ;Is mode > 0 ?
  138.         jz    CaInit_out        ;Leave if mode_num = 0
  139.         cmp    bx,maxmode        ;Mode in range?
  140.         ja    CaInit_out        ;No -- leave
  141.         dec    bx            ;Else BX = mode - 1
  142.         add    bx,bx            ;BX = (mode - 1) * 2
  143.         mov    bx,[modetbl + bx]    ;BX = addr. of mode structure
  144. ; Now get info about this mode
  145.         mov    ax,[bx].mrows        ;Number of rows
  146.         mov    rows,ax
  147.         mov    ax,[bx].mcols        ;Number of columns
  148.         mov    cols,ax
  149.         mov    ax,[bx].mvidseg        ;Video buffer segment addr.
  150.         mov    vidseg,ax
  151.         mov    ax,[bx].mclear        ;Video clear routine
  152.         mov    disp_clear_addr,ax
  153.         mov    ax,[bx].mdisp        ;Video display routine
  154.         mov    disp_buf_addr,ax
  155.         mov    ax,[bx].mbufclr        ;Buffer clear routine
  156.         mov    buf_clear_addr,ax
  157.         mov    ax,[bx].mvoffset    ;Color/Char. selector
  158.         mov    voffset,ax
  159.         mov    ax,[bx].mrowrep        ;Graphics row dupl. count
  160.         mov    row_repeat,ax
  161.         mov    ax,[bx].mdotrep        ;Graphics dot dupl. count
  162.         mov    dot_repeat,ax
  163.         mov    al,[bx].mchar        ;Default display character
  164.         mov    clear_char,al
  165.         mov    al,[bx].mcolor        ;Display display color
  166.         mov    clear_color,al
  167.         mov    al,[bx].mborder        ;Border value
  168.         mov    border_val,al
  169.         mov    ax,1            ;Turn borders on
  170.         mov    border_on,ax
  171.  
  172.         mov    ax,array_ptr        ;Get array address
  173.         mov    cell_array,ax
  174.         sub    ah,ah            ;AH=0: Set video mode
  175.         mov    al,[bx].mvmode        ;Get new mode
  176.         int    10h            ;Set & clear screen
  177.         call    calc_buf_size        ;Calculate buffer stats.
  178.         call    clear_buf        ;Initialize buffer
  179.         mov    ax,1            ;Show success
  180. CaInit_out:    ret
  181. CaInit        endp
  182.  
  183. ;************
  184. ; CaReset -- Restores original video mode
  185. ;    Call: CaReset
  186. ;    Return: None
  187. ;************
  188.     Public    CaReset
  189. CaReset        proc    far
  190.         test    original_mode,-1    ;Has a mode been set?
  191.         jz    @F            ;No -- just leave
  192.         mov    ax,original_mode    ;Get original video mode
  193.         int    10h            ;BIOS: Set mode
  194.         sub    ax,ax            ;AX = 0
  195.         mov    original_mode,ax    ;Show no mode set
  196.     @@:    ret
  197. CaReset        endp
  198.  
  199. ;************
  200. ;  CaWrap turns on or off side-to-side wrap around of the universe
  201. ;    Call:    CaWrap (num)  If Num = 0, wrap is turned off (the default)
  202. ;                 else wrap is turned on
  203. ;    Return: none
  204. ;************
  205.     Public    CaWrap
  206. CaWrap        proc    far val
  207.         test    original_mode,-1    ;Has a mode been set?
  208.         jz    @F            ;No -- just leave
  209.         cmp    word ptr [val],1    ;Is val <> 0 ?
  210.         sbb    ax,ax            ;AX = -1 or 0
  211.         inc    ax            ;AX = 0 or 1
  212.         mov    border_on,ax        ;Save value
  213.         call    calc_buf_size        ;Make new buffer stats
  214.         call    clear_buf        ;Clear the buffer
  215.         call    [disp_clear_addr]    ;  and the display
  216.     @@:    ret
  217. CaWrap        endp
  218.  
  219. ;************
  220. ;  CaBorder -- Set new value for the borders or edges of universe
  221. ;    Call:   CaBorder (new_border_value)
  222. ;    Return:    none
  223. ;************
  224.     Public    CaBorder
  225. CaBorder    proc    far val
  226.         test    original_mode,-1    ;Has a mode been set?
  227.         jz    @F            ;No -- just leave
  228.         mov    ax,val            ;Get new value
  229.         mov    border_val,al        ;  and save it
  230.         call    clear_buf        ;Clear the buffer
  231.         call    [disp_clear_addr]    ;  and the display
  232.     @@:    ret
  233. CaBorder    endp
  234.  
  235. ;************
  236. ;  CaChar -- Set new default display character for text modes
  237. ;    Call:    CaChar (new_char_value)
  238. ;    Return: none
  239. ;************
  240.     Public    CaChar
  241. CaChar        proc    far val
  242.         test    original_mode,-1    ;Has a mode been set?
  243.         jz    @F            ;No -- just leave
  244.         mov    ax,val            ;Get new value
  245.         mov    [clear_char],al        ;Save just the character
  246.         call    clear_buf        ;Clear the buffer
  247.         call    [disp_clear_addr]    ;  and the display
  248.     @@:    ret
  249. CaChar        endp
  250.  
  251. ;************
  252. ;  CaColor -- Set new default display color
  253. ;    Call:    CaColor (new_color_value)
  254. ;    Return:    none
  255. ;************
  256.     Public    CaColor
  257. CaColor        proc    far val
  258.         test    original_mode,-1    ;Has a mode been set?
  259.         jz    @F            ;No -- just leave
  260.         mov    ax,val            ;Get new value
  261.         mov    [clear_color],al    ;Save just the color
  262.         call    clear_buf        ;Clear the buffer
  263.         call    [disp_clear_addr]    ;  and the display
  264.     @@:    ret
  265. CaColor        endp
  266.  
  267. ;************
  268. ;  CaClear -- Clear the buffer and the display
  269. ;    Call:    CaClear
  270. ;    Return:    none
  271. ;************
  272.     Public    CaClear
  273. CaClear        proc    far
  274.         test    original_mode,-1    ;Has a mode been set?
  275.         jz    @F            ;No -- just leave
  276.         call    clear_buf        ;Clear the buffer
  277.         call    [disp_clear_addr]    ;  and the display
  278.     @@:    ret
  279. CaClear        endp
  280.  
  281. ;************
  282. ;  CaSize -- Set row, column, row-repeat, and dot-repeat values
  283. ;         Only has an effect in CGA and EGA graphics modes
  284. ;    Call:    CaRows (rows_shown, cols_shown, row_repeat, dot_repeat)
  285. ;    Return:    none
  286. ;************
  287.     Public    CaSize
  288. CaSize        proc    far rows_shown, cols_shown, row_rpt, dot_rpt
  289.         test    original_mode,-1    ;Has a mode been set?
  290.         jz    @F            ;No -- just leave
  291.         mov    ax,rows_shown        ;Get # of rows
  292.         mov    rows,ax            ;And save it
  293.         mov    ax,cols_shown        ;Same for # of columns
  294.         mov    cols,ax
  295.         mov    ax,row_rpt        ;Row-repeat value
  296.         mov    row_repeat,ax
  297.         mov    ax,dot_rpt           ;And dot-repeat value
  298.         mov    dot_repeat,ax
  299.         call    calc_buf_size        ;Recalculate buffer params.
  300.         call    clear_buf        ;Clear the buffer
  301.         call    [disp_clear_addr]    ;  and the display
  302.     @@:    ret
  303. CaSize        endp
  304.  
  305. ;************
  306. ;  CaSet -- Set one cell in the buffer to a specific value
  307. ;    Call:    CaSet (row, column, value)
  308. ;    Return:    none
  309. ;************
  310.     Public    CaSet
  311. CaSet        proc    far uses di es, row, col, val
  312.         les    di,bufaddr        ;ES:DI ==> universe buffer
  313.         test    border_on,-1        ;Borders turned on?
  314.         jnz    @F            ;Yes -- go
  315.         dec    col            ;Else make column 0-based
  316.     @@:    mov    ax,row            ;Get row number
  317.         mul    [bufcols]        ; Row * cols_per_row
  318.         add    ax,col            ;Offset into buffer
  319.         mov    bx,ax            ;BX has offset
  320.         mov    ax,val            ;Get value
  321.         mov    es:[di+bx],al        ;Store new value
  322.         ret
  323. CaSet        endp
  324.  
  325. ;************
  326. ;  CaShow -- Display current contents of universe buffer
  327. ;    Call:    CaShow
  328. ;    Return:    none
  329. ;************
  330.     Public    CaShow
  331. CaShow        proc    far
  332.         test    original_mode,-1    ;Has a mode been set?
  333.         jz    @F            ;No -- just leave
  334.         call    [disp_buf_addr]        ;Call correct routine
  335.     @@:    ret
  336. CaShow        endp
  337.  
  338. ;************
  339. ;  CaGen -- Create a new generation of the universe and display it
  340. ;    Call:    CaGen
  341. ;    Return:    none
  342. ;    Calls user's CaCell routine for each cell in the universe
  343. ;************
  344.     Public    CaGen
  345. CaGen        proc    far uses di si es
  346.         test    original_mode,-1    ;Has a mode been set?
  347.         jnz    @F            ;Yes -- get to work
  348.         jmp    CaGen_out        ;Else just leave
  349.     @@:    les    si,bufaddr        ;ES:SI ==> universe buffer
  350.         mov    di,bufsize        ;DI = bytes in use
  351.         add    di,si            ;ES:DI ==> buffer free space
  352.         mov    cx,bufcols        ;CX = columns in buffer
  353.     @@:    mov    al,es:[si]        ;Get byte of border
  354.         inc    si            ;Point to next
  355.         stosb                ;Store in next generation
  356.         loop    @B            ;Do whole border
  357.         
  358.         mov    cx,1            ;CX counts rows
  359. CaGen_1:    test    border_on,-1        ;Side borders turned on?
  360.         jz    @F            ;No -- jump forward
  361.         mov    al,es:[si]        ;Else get border byte
  362.         inc    si            ;Point to first cell
  363.         stosb                ;Store in next generation
  364.  
  365.     @@:    mov    dx,1            ;DX counts columns
  366. CaGen_2:    push    di            ;Save pointer
  367.         mov    di,cell_array        ;DS:DI ==> user's data array
  368.         mov    [di+18],cx        ;Save row number
  369.         mov    [di+20],dx        ;  and column number
  370.         push    cx            ;Save counters
  371.         push    dx
  372.         sub    ah,ah            ;AH = 0 always
  373.         mov    bx,bufcols        ;BX = columns in buffer
  374.         neg    bx            ;BX = -BX
  375.         
  376.         mov    al,es:[si+bx-1]        ;Get NW neighbor
  377.         mov    [di],ax            ;Save it
  378.         add    di,2            ;Point to next array item
  379.         mov    al,es:[si+bx]        ;Get North neighbor
  380.         mov    [di],ax
  381.         add    di,2
  382.         mov    al,es:[si+bx+1]        ;Get NE neighbor
  383.         mov    [di],ax
  384.         add    di,2
  385.  
  386.         mov    al,es:[si-1]        ;Get West neighbor
  387.         mov    [di],ax
  388.         add    di,2
  389.         mov    al,es:[si]        ;Get current cell
  390.         mov    [di],ax
  391.         add    di,2
  392.         mov    al,es:[si+1]        ;Get East neighbor
  393.         mov    [di],ax
  394.         add    di,2
  395.  
  396.         neg    bx            ;BX = bufcols
  397.         mov    al,es:[si+bx-1]        ;Get SW neighbor
  398.         mov    [di],ax
  399.         add    di,2
  400.         mov    al,es:[si+bx]        ;Get South neighbor
  401.         mov    [di],ax
  402.         add    di,2
  403.         mov    al,es:[si+bx+1]        ;Get SE neighbor
  404.         mov    [di],ax
  405.         
  406.         call    CaCell            ;Let user calculate new value
  407.         pop    dx            ;Recover registers
  408.         pop    cx
  409.         pop    di
  410.         stosb                ;Store new value
  411.         inc    si            ;Point to next cell
  412.         inc    dx            ;Move to next column
  413.         cmp    dx,cols            ;Done with this row?
  414.         jle    CaGen_2            ;No -- go do another
  415.  
  416.         test    border_on,-1        ;Ready for right border
  417.         jz    @F            ;Go if no border
  418.         mov    al,es:[si]        ;Else get border value
  419.         inc    si            ;Point to next position
  420.         stosb                ;Save in next generation
  421.     @@:    inc    cx            ;One row done
  422.         cmp    cx,rows            ;Are they all done?
  423.         jg    @F            ;Yes -- do bottom border
  424.         jmp    CaGen_1            ;Else do another row
  425.     @@:    mov    cx,[bufcols]        ;Else get columns in CX
  426.     @@:    mov    al,es:[si]        ;Get border value
  427.         inc    si            ;Point to next
  428.         stosb                ;Save that value
  429.         loop    @B            ;And do the rest
  430.  
  431.         mov    ax,bufsize        ;Get bytes in universe
  432.         add    bufstart,ax        ;Set new beginning addr.
  433.         call    [disp_buf_addr]        ;Show this buffer
  434. CaGen_out:    ret
  435. CaGen        endp
  436.  
  437. ;************
  438. ;  Internal Routines -- all of the following routines are for
  439. ;      internal use only and are NOT available to the user
  440. ;
  441. ;  calc_buf_size: calculates and stores number of columns per row in 
  442. ;        the buffer (bufcols) and the total size of the
  443. ;        buffer (bufsize)
  444. ;************
  445.  
  446. calc_buf_size    proc    near
  447.         mov    bx,border_on        ;Get border count
  448.         add    bx,bx            ;Doubled for both sides
  449.         add    bx,cols            ;Add display columns
  450.         mov    [bufcols],bx        ;Save total
  451.         mov    ax,rows            ;AX = display rows
  452.         add    ax,2            ;Add top & bottom border
  453.         mul    bx            ;bufsize = AX * BX
  454.         mov    bufsize,ax        ;Save value
  455.         ret
  456. calc_buf_size    endp
  457.  
  458. ;************
  459. ;  clear_buf -- sets the buffer to its clear (default) values
  460. ;************
  461. clear_buf    proc    near uses di es
  462.         mov    es,bufseg        ;ES ==> buffer
  463.         sub    di,di            ;ES:DI ==> start of buffer
  464.         jmp    [buf_clear_addr]    ;Select correct routine
  465. txt_buf_clear:                    ;For text:
  466.         mov    al,clear_char        ;  Get character to use
  467.         jmp    short @F        ;  and go to work
  468. clr_buf_clear:                    ;For color
  469.         mov    al,clear_color        ;  Get color to use
  470.     @@:    mov    ah,al            ;Duplicate value
  471.         mov    cx,8000h        ;Words in buffer
  472.         rep    stosw            ;Clear entire buffer
  473.         sub    di,di            ;ES:DI ==> beginning again
  474.         mov    cx,bufcols        ;CX = bytes in a column
  475.         mov    al,border_val        ;AL = value for border
  476.         rep    stosb            ;Make top border
  477.         test    border_on,-1        ;Are side borders needed?
  478.         jz    clear_buf_1        ;No -- go
  479.         mov    cx,rows            ;Else CX = display rows
  480.         mov    bx,cols            ;     BX = display columns
  481.     @@:    stosb                ;Store left border
  482.         add    di,bx            ;Move to right border
  483.         stosb                ;Store right border
  484.         loop    @B            ;Do all rows
  485. clear_buf_1:    mov    di,bufsize        ;DI ==> past end of buffer
  486.         sub    di,bufcols        ;DI ==> bottom border
  487.         mov    cx,bufcols        ;CX = columns in border
  488.         rep    stosb            ;Make bottom border
  489.         sub    ax,ax            ;AX = 0
  490.         mov    bufstart,ax        ;New starting offset
  491.         ret
  492. clear_buf    endp
  493.  
  494. ;************
  495. ;  txt_disp_clear -- Clear the monochrome or CGA text display screen
  496. ;************
  497. txt_disp_clear    proc    near uses di es
  498.         mov    es,[vidseg]        ;ES==> video buffer
  499.         mov    ax,[rows]        ;AX = rows on screen
  500.         mul    [cols]            ;AX = positions on screen
  501.         mov    cx,ax            ;CX = screen positions
  502.         mov    ax,clear_val        ;AX = char & color for clear
  503.         sub    di,di            ;ES:DI==> start of screen
  504.         rep    stosw            ;Fill the screen
  505.         ret
  506. txt_disp_clear    endp
  507.  
  508. ;************
  509. ;  CGA_disp_clear -- Clear the CGA 4-color graphics screen
  510. ;************
  511. CGA_disp_clear    proc    near uses di es
  512.         mov    es,[vidseg]        ;ES==> video buffer
  513.         mov    al,clear_color        ;Color in AL
  514.         and    al,03h            ;Use only 2 bits
  515.         mov    cl,2            ;To shift 2 bits at a time
  516.         mov    ah,al            ;Color in AH: xxxx xxCC
  517.         shl    al,cl            ;Move color to bits 2 & 3
  518.         or    ah,al            ;Color in AH: xxxx CCCC
  519.         shl    al,cl            ;Move color to bits 4 & 5
  520.         or    ah,al            ;Color in AH: xxCC CCCC
  521.         shl    al,cl            ;Move color to bits 6 & 7
  522.         or    ah,al            ;Color in AH: CCCC CCCC
  523.         mov    al,ah            ;Color in AH & AL
  524.         mov    cx,2000h        ;Size of video buffer
  525.         sub    di,di            ;ES:DI ==> start of video
  526.         rep    stosw            ;Fill video buffer
  527.         ret
  528. CGA_disp_clear    endp
  529.  
  530. ;************
  531. ;  EGA_disp_clear -- clear the EGA graphics display (mode 10h)
  532. ;************
  533. EGA_disp_clear    proc    near uses di es
  534.         mov    es,[vidseg]
  535.         sub    di,di            ;ES:DI ==> start of video
  536.         mov    dx,3ceh            ;EGA Graph. controller port
  537.         mov    ah,clear_color        ;Color in AH
  538.         sub    al,al            ;AL = 0 = Set/Reset register
  539.         out    dx,al            ;Put color in Set/Reset reg.
  540.         mov    ax,0f01h        ;Enable Set/Reset reg.
  541.         out    dx,ax            ;  for all planes
  542.         mov    cx,40 * 350        ;Words to clear
  543.         rep    stosw            ;Clear display
  544.         mov    ax,0001            ;Disable Set/Reset reg.
  545.         out    dx,ax            ;  for all planes
  546.         ret
  547. EGA_disp_clear    endp
  548.  
  549. ;************
  550. ;  txt_disp_buf    -- display the universe in text-based modes (CGA, MDA or EGA)
  551. ;************
  552.  
  553. txt_disp_buf    proc    near uses di si ds es
  554.         local    lbrdr_on
  555.         mov    ax,border_on        ;Copy border flag
  556.         mov    lbrdr_on,ax        ;  to SS seg
  557.  
  558.         mov    es,[vidseg]
  559.         sub    di,di            ;ES:DI ==> video buffer
  560.         add    di,voffset        ;Adjust for text/attributes
  561.         mov    cx,rows            ;CX will count rows
  562.         mov    dx,cols            ;DX counts columns
  563.         mov    bx,bufcols        ;BX = columns in buffer
  564.         lds    si,bufaddr        ;DS:SI ==> universe buffer
  565.         add    si,bx            ;DS:SI ==> 1st row past border
  566. txt_disp_1:    push    cx            ;Save row count
  567.         mov    cx,dx            ;Column count in cx
  568.         add    si,lbrdr_on        ;Skip left border
  569.         push    di            ;Save vid buffer addr.
  570.     @@:    lodsb                ;Read and show
  571.         stosb                ;  one cell (color or char
  572.         inc    di            ;  only) and ready for next
  573.         loop    @B
  574.         add    si,lbrdr_on        ;Skip right border
  575.         pop    di            ;Get back to row beginning
  576.         add    di,160            ;Spaces in a row
  577.         pop    cx            ;Get row counter
  578.         loop    txt_disp_1        ;Do for all rows
  579.         ret
  580. txt_disp_buf    endp
  581.  
  582. ;************
  583. ;  CGA_disp_buf -- Displays the universe using CGA 4-color, 320x200 graphics
  584. ;************
  585. CGA_disp_buf    proc    near uses di si ds es
  586.         local    lrow_rpt, ldot_rpt, lbufcols
  587.         local    lcols, lrows, lend_col, lendcol_flag
  588.         mov    bx,border_on        ;Get border flag
  589.         mov    ax,row_repeat        ;Copy values so we 
  590.         mov    lrow_rpt,ax        ;  can get to them
  591.         mov    ax,dot_repeat        ;  through SS instead
  592.         mov    ldot_rpt,ax        ;  of DS
  593.         mov    ax,bufcols
  594.         mov    lbufcols,ax
  595.         mov    ax,cols
  596.         mov    lcols,ax
  597.         mov    ax,rows
  598.         mov    lrows,ax
  599.  
  600.         mov    es,[vidseg]
  601.         sub    di,di            ;ES:DI ==> video buffer
  602.         lds    si,bufaddr        ;DS:SI ==> universe buffer
  603.         add    si,lbufcols        ;Skip top border
  604.         add    si,bx            ; and left border
  605. CGA_disp_1:    push    si            ;Save buffer pointers
  606.         push    di
  607.         mov    ax,si            ;Get start column
  608.         add    ax,lcols        ;AX = last col in row + 1
  609.         mov    lend_col,ax        ;Save the value
  610.         sub    ax,ax            ;AX = 0
  611.         mov    lendcol_flag,ax        ;Turn the flag off
  612.         mov    bx,ldot_rpt        ;BX counts dot repeats
  613. CGA_disp_2:    mov    cx,4            ;4 dots per graphics byte
  614.         sub    ax,ax            ;Clear accumulator
  615. CGA_disp_3:    mov    al,[si]            ;Get byte
  616.         and    al,03h            ;Keep 2 bits
  617.         shl    ah,1            ;Move over old value
  618.         shl    ah,1            ;  to make room for the new
  619.         or    ah,al            ;Store new value
  620.         dec    bx            ;Count the dot
  621.         jnz    @F            ;Go if more of same to come
  622.         inc    si            ;Else point to next cell
  623.         mov    bx,ldot_rpt        ;  and reload count
  624.         cmp    si,lend_col        ;End of column?
  625.         jne    @F            ;No -- go
  626.         inc    lendcol_flag        ;Else set flag
  627.     @@:    loop    CGA_disp_3        ;Get all 4 dots
  628.     
  629.         mov    cx,lrow_rpt        ;Rows to repeat
  630.         push    di            ;Save video ptr
  631. CGA_disp_4:    mov    es:[di],ah        ;Store this value
  632.         add    di,2000h        ;Move to next line
  633.         cmp    di,4000h        ;Time to move back?
  634.         jb    @F            ;No -- go
  635.         sub    di,4000h-80        ;Yes -- back to top half
  636.     @@:    loop    CGA_disp_4        ;Display it all
  637.         pop    di            ;Recover video ptr
  638.         inc    di            ;Move to next position
  639.         test    lendcol_flag,-1        ;End of this row?
  640.         jz    CGA_disp_2        ;No -- do some more
  641.  
  642. CGA_disp_5:    pop    di            ;Get start of line
  643.         mov    cx,lrow_rpt        ;Get repeat count
  644. CGA_disp_6:    add    di,2000h        ;Move to next row
  645.         cmp    di,4000h        ;Was at bottom?
  646.         jb    @F            ;No -- go
  647.         sub    di,4000h-80        ;Else move back up
  648.     @@:    loop    CGA_disp_6        ;Repeat as needed
  649.  
  650.         pop    si            ;Get line position
  651.         add    si,lbufcols        ;Move to next
  652.         dec    lrows            ;Count one row
  653.         jnz    CGA_disp_1        ;Do next row
  654.         ret
  655. CGA_disp_buf    endp
  656.  
  657. ;************
  658. ;  EGA_disp_buf -- Displays the universe using EGA 16-color, 640x350 graphics
  659. ;************
  660. EGA_disp_buf    proc    near uses di si ds es
  661.         local    lrow_rpt, ldot_rpt, lbufcols
  662.         local    lcols, lrows, lend_col, lendcol_flag
  663.         mov    bx,border_on        ;Get border flag
  664.         mov    ax,row_repeat        ;Copy values so we 
  665.         mov    lrow_rpt,ax        ;  can get to them
  666.         mov    ax,dot_repeat        ;  through SS instead
  667.         mov    ldot_rpt,ax        ;  of DS
  668.         mov    ax,bufcols
  669.         mov    lbufcols,ax
  670.         mov    ax,cols
  671.         mov    lcols,ax
  672.         mov    ax,rows
  673.         mov    lrows,ax
  674.         
  675.         mov    dx,3ceh            ;EGA/VGA Graphics port
  676.         mov    ax,0205h        ;Select write mode 2
  677.         out    dx,ax
  678.         
  679.         mov    es,[vidseg]
  680.         sub    di,di            ;ES:DI ==> video buffer
  681.         lds    si,bufaddr        ;DS:SI ==> universe buffer
  682.         add    si,lbufcols        ;Skip top border
  683.         add    si,bx            ; and left border
  684.  
  685. EGA_disp_1:    push    si            ;Save buffer pointers
  686.         push    di
  687.         mov    ax,si            ;Get start column
  688.         add    ax,lcols        ;AX = last col + 1
  689.         mov    lend_col,ax        ;Save the value
  690.         sub    ax,ax            ;AX = 0
  691.         mov    lendcol_flag,ax        ;Turn the flag off
  692.         mov    bx,ldot_rpt        ;BX = times to repeat a dot
  693.  
  694.         mov    ah,80h            ;Bit mask
  695.         mov    al,08h            ;Bit mask register
  696. EGA_disp_2:    mov    bh,[si]            ;Get a value
  697.         out    dx,ax            ;Select 1-pixel mask
  698.         mov    cl,es:[di]        ;Set EGA latches
  699.         mov    es:[di],bh        ;Set the dot
  700.         dec    bl            ;Count one dot
  701.         jnz    @F            ;Go if more of the same
  702.         inc    si            ;Else move to next place
  703.         mov    bx,ldot_rpt        ; and pick up counter
  704.         cmp    si,lend_col        ;At end of the row?
  705.         jne    @F            ;No -- go
  706.         inc    lendcol_flag        ;Yes -- set flag
  707.     @@:    clc                ;Clear carry flag
  708.         rcr    ah,1            ;Move bit mask right
  709.         jnc    EGA_disp_2        ;Repeat until carry set
  710.  
  711.         mov    cx,lrow_rpt        ;Get row repeat count
  712.         dec    cx            ;Reduce by 1
  713.         jcxz    EGA_disp_3        ;Go if no repeat
  714.         sub    ah,ah            ;Bit mask = 0
  715.         out    dx,ax            ;Set bit mask
  716.         mov    bh,es:[di]        ;Set latches
  717.         push    di            ;Save video pointer
  718.     @@:    add    di,80            ;Move to next line
  719.         mov    es:[di],bh        ;Copy byte
  720.         loop    @B            ;For all repeats
  721.         pop    di            ;Get back original
  722. EGA_disp_3:    inc    di            ;Move to next position
  723.         mov    ah,80h            ;Set new bit mask
  724.         test    lendcol_flag,-1        ;Done with this row?
  725.         jz    EGA_disp_2        ;No -- do some more dots
  726.         pop    di            ;Else pop original
  727.         pop    si            ;  pointers
  728.         dec    lrows            ;Count one row
  729.         jz    EGA_disp_4        ;Go if done
  730.  
  731.         add    si,lbufcols        ;Move to next buffer row
  732.         mov    cx,lrow_rpt        ;Get row repeat count
  733.     @@:    add    di,80            ;Move down required rows
  734.         loop    @B
  735.         jmp    EGA_disp_1        ;Loop back for another row
  736.  
  737. EGA_disp_4:    mov    ax,0ff08h        ;Put bit mask back to normal
  738.         out    dx,ax
  739.         mov    ax,00005h        ;Restore write mode 0
  740.         out    dx,ax
  741.         ret
  742. EGA_disp_buf    endp
  743.  
  744.  
  745. ;  Use the following segment definition for Micrsoft languages: 
  746. ;       Quick Basic, Quick C, MSC
  747. ca_buf        segment
  748.  
  749. ;  Use the following segment definition for Turbo C.  The line will work 
  750. ;  but cause a Link warning if used with Microsoft languages.
  751. ;ca_buf        segment para public 'CODE'
  752.  
  753.     dw    8000h dup (?)
  754. ca_buf        ends
  755.  
  756.         end
  757.